home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 12 / Mac Magazin and MacEasy Magazine CD - Issue 12.iso / Sharewarebibliothek / Anwendungen / Wissenschaft & Technik / ResAnomaly 1.1 / ResAnomaly Source / FrDropApp.cp next >
Text File  |  1995-07-03  |  9KB  |  378 lines

  1.  
  2. // * This is ResAnomaly.        Based on FrDropApp
  3. // * ©1995 Chris K. Thomas.        ©1994 Metrowerks Inc. All Rights Reserved.
  4.  
  5.  
  6. /*
  7.     ckt July the Second 1995
  8.     
  9.     Grab text resources up front to support the current architecture of
  10.     ResAnomaly. Eventually, I think we're going to go to three stages:
  11.     
  12.         …resource file is open
  13.     Stage One:      Data retrieval.  Gather all the named resources
  14.                     in the file into a list.
  15.         …resource file is closed
  16.     
  17.     Stage Two:      Analysis.  Check to be sure
  18.                     there aren't duplicate names & other stuff
  19.     
  20.     Stage Three:    Emitter.  Write the data in the proper format
  21.                     to the output stream.
  22.     
  23.     Currently, we only effectively have a mixed version of stages 1 & 3,
  24.     and the resource file is open throughout, which makes it difficult
  25.     to get to our own resources without abusing the Resource Mangler.
  26. */
  27.  
  28. #define DEBUG_ME Yes, Please
  29.  
  30. #if  (defined DEBUG_ME) && (defined __powerc)
  31. #pragma traceback on
  32. #endif
  33.  
  34. // ————• Us
  35. #include "FrDropApp.h"
  36. #include "ResAnomaly Settings.h"
  37.  
  38. // ————• PP
  39. #include <UException.h>
  40. #include <LModelDirector.h>
  41. #include <LFileStream.h>
  42. #include <UAppleEventsMgr.h>
  43. #include <LHandleStream.h>
  44. #include <UMemoryMgr.h>
  45.  
  46. // ————• my less annoying (to the programmer) standard file replacement
  47. #include "StFile.h"
  48.  
  49. const ResIDT    ALRT_NoFiles    = 200;
  50.  
  51. static void InsertTextIntoStream(Handle inOurResource, LStream &inStream);
  52. static void InsertTextIntoStream(short inID, LStream &inStream);
  53. static void AddDotExtension(Str255 ioString, const Str255 inDot);
  54. static void MapToValidC(Str255 ioString);
  55.  
  56.  
  57. // ===========================================================================
  58. //        • Main Program
  59. // ===========================================================================
  60.  
  61. void main(void)
  62. {
  63.     try
  64.     {
  65.         FrDropApp    gApp;
  66.         gApp.Run();
  67.     }
  68.     catch(...)
  69.     {
  70.         
  71.     }
  72. }
  73.  
  74.  
  75. // ===========================================================================
  76. //        • FrDropApp Class
  77. // ===========================================================================
  78.  
  79. FrDropApp::FrDropApp()
  80. {
  81.     MaxApplZone();
  82.  
  83.     InitGraf((Ptr) &qd.thePort);        // Toolbox Managers
  84.     InitFonts();
  85.     InitWindows();
  86.     InitMenus();
  87.     TEInit();
  88.     InitDialogs(nil);
  89.     
  90.     new LModelDirector(this);            // AppleEvent Handlers
  91.     
  92.     mRunning = true;
  93.     
  94.     // * preload our text, because we can't access
  95.     // * our res file during processing
  96.     
  97.     mTextBeginLine = Get1Resource('TEXT', 128);
  98.     mTextIDequals = Get1Resource('TEXT', 130);
  99.     mTextIDend = Get1Resource('TEXT', 131);
  100.     mOutputHeaderStart = Get1Resource('TEXT', 256);
  101.     mOutputHeaderStop = Get1Resource('TEXT', 257);
  102.     
  103.     ThrowIfNULL_(mTextBeginLine);
  104.     ThrowIfNULL_(mTextIDequals);
  105.     ThrowIfNULL_(mTextIDend);
  106.     ThrowIfNULL_(mOutputHeaderStart);
  107.     ThrowIfNULL_(mOutputHeaderStop);
  108. }
  109.  
  110.  
  111. void
  112. FrDropApp::Run()
  113. {
  114.         // This program has no user interface. We only care
  115.         // about AppleEvents.
  116.         
  117.     while (mRunning) {
  118.         EventRecord        macEvent;
  119.         if (WaitNextEvent(everyEvent, &macEvent, 2, nil)) {
  120.         
  121.             if (macEvent.what == kHighLevelEvent) {
  122.                 AEProcessAppleEvent(&macEvent);
  123.             }
  124.         }
  125.     }
  126. }
  127.  
  128.  
  129. void
  130. FrDropApp::HandleAppleEvent(
  131.     const AppleEvent    &inAppleEvent,
  132.     AppleEvent            &outAEReply,
  133.     AEDesc                &outResult,
  134.     long                inAENumber)
  135. {
  136.     switch (inAENumber) {
  137.     
  138.         case ae_OpenApp:
  139.             StartUp();
  140.             break;
  141.             
  142.         case ae_OpenDoc:
  143.             DoAEOpenDoc(inAppleEvent, outAEReply, inAENumber);
  144.             break;
  145.             
  146.         case ae_Quit:
  147.             DoQuit();
  148.             break;
  149.             
  150.         default:
  151.             LModelObject::HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  152.             break;
  153.     }
  154. }
  155.  
  156.  
  157. void
  158. FrDropApp::StartUp()
  159. {
  160.         // User double-clicked on the Program's icon
  161.         
  162.         // This program only works when files are dragged on the
  163.         // program's icon in the Finder. So we just display an
  164.         // Alert (which could have instructions for using the program)
  165.         // and then quit.
  166.     
  167.     ::Alert(ALRT_NoFiles, nil);
  168.     DoQuit();
  169. }
  170.  
  171.  
  172. void
  173. FrDropApp::DoAEOpenDoc(
  174.     const AppleEvent    &inAppleEvent,
  175.     AppleEvent&            /*outAEReply*/,
  176.     long                /*inAENumber*/)
  177. {
  178.     AEDescList    docList;
  179.     OSErr        err = AEGetParamDesc(&inAppleEvent, keyDirectObject,
  180.                             typeWildCard, &docList);
  181.     if (err != noErr) Throw_(err);
  182.     
  183.     Int32    numDocs;
  184.     err = AECountItems(&docList, &numDocs);
  185.     if (err != noErr) Throw_(err);
  186.     
  187.         // Loop through all items in the list
  188.             // Extract descriptor for the document
  189.             // Coerce descriptor data into a FSSpec
  190.             // Tell Program object to open document
  191.         
  192.     for (Int32 i = 1; i <= numDocs; i++) {
  193.         AEKeyword    theKey;
  194.         DescType    theType;
  195.         FSSpec        theFileSpec;
  196.         Size        theSize;
  197.         err = AEGetNthPtr(&docList, i, typeFSS, &theKey, &theType,
  198.                             (Ptr) &theFileSpec, sizeof(FSSpec), &theSize);
  199.         if (err != noErr) Throw_(err);
  200.         OpenDocument(&theFileSpec);
  201.     }
  202.     
  203.     AEDisposeDesc(&docList);
  204.     
  205.     DoQuit();
  206. }
  207.  
  208.  
  209. void
  210. FrDropApp::OpenDocument(
  211.     FSSpec    *inMacFSSpec)
  212. {
  213.     FSSpec            saveSpec = *inMacFSSpec;
  214.     Handle            curRes;
  215.     long            numTypes;
  216.     long            numRes;
  217.     long            i, j;
  218.     short            currentID;
  219.     ResType            currentType;
  220.     Str255            currentName;
  221.     Str255            numString;
  222.     LHandleStream    ourStream;
  223.     
  224.     InsertTextIntoStream(mOutputHeaderStart, ourStream);
  225.     ourStream.WriteData(&inMacFSSpec->name[1], inMacFSSpec->name[0]);
  226.     InsertTextIntoStream(mOutputHeaderStop, ourStream);
  227.     
  228.     Try_{
  229.         LFile            resFile(*inMacFSSpec);
  230.  
  231.         SetResLoad(false);
  232.         resFile.OpenResourceFork(fsRdPerm);
  233.         SetResLoad(true);
  234.         
  235.         numTypes = Count1Types();
  236.         
  237.         for(i = 1; i <= numTypes; i++)
  238.         {
  239.             Get1IndType(¤tType, i);
  240.             ThrowIfResError_();
  241.             
  242.             numRes = Count1Resources(currentType);
  243.             ThrowIfResError_();
  244.             
  245.             for(j = 1; j <= numRes; j++)
  246.             {
  247.                 SetResLoad(false);
  248.                 curRes = Get1IndResource(currentType, j);
  249.                 SetResLoad(true);
  250.                 
  251.                 ThrowIfResError_();
  252.                 ThrowIfNULL_(curRes);
  253.                 
  254.                 GetResInfo(curRes, ¤tID, NULL, currentName);
  255.                 ThrowIfResError_();
  256.                 
  257.                 // * if the resource isn't named, how does one identify it?
  258.                 if(currentName[0] > 0)
  259.                 {
  260.                     MapToValidC(currentName);    //convert name to C-language usable
  261.                     
  262.                     // * Write a type string in the format const short kResNameType = 'type';
  263.                     
  264.     //                    InsertTextIntoStream(128, ourStream);    // "const kResource"
  265.     //                    ourStream.WriteData(¤tName[1], currentName[0]); // "<name>"
  266.     //                    InsertTextIntoStream(129, ourStream);    // "Type = '"
  267.     //                    ourStream.WriteData(¤tType, sizeof(ResType)); // "tnam"
  268.     //                    InsertTextIntoStream(131, ourStream);    // "';\r"
  269.                     
  270.                     // * Write an ID string in the format const short kResNameID = id#;
  271.                     InsertTextIntoStream(mTextBeginLine, ourStream);    // "const kResource"
  272.                     ourStream.WriteData(¤tName[1], currentName[0]); // "<name>"
  273.                     ourStream.WriteData(¤tType, sizeof(ResType));    //tnam
  274.                     InsertTextIntoStream(mTextIDequals, ourStream);    // "ID = '"
  275.                     NumToString(currentID, numString);
  276.                     ourStream.WriteData(&numString[1], numString[0]);
  277.                     InsertTextIntoStream(mTextIDend, ourStream);    // "';\r"
  278.                 }
  279.                 
  280.                 ReleaseResource(curRes);
  281.             }
  282.         }
  283.  
  284.         resFile.CloseResourceFork();
  285.         
  286.         // * we can now safely access our own resources
  287.         
  288.         AddDotExtension(inMacFSSpec->name, kDefaultDotExtension);
  289.     
  290.         StPutFile    newFile("\pSave Resource Constants as:", *inMacFSSpec);
  291.         
  292.         if(newFile.reply.sfGood)
  293.         {
  294.             LFile        ourFile(newFile.reply.sfFile);
  295.             
  296.             if(newFile.reply.sfReplacing)
  297.                 ThrowIfOSErr_(FSpDelete(&newFile.reply.sfFile));
  298.             
  299.             ourFile.CreateNewDataFile(kTextFileCreator, 'TEXT');
  300.             
  301.             StHandleLocker stlock(ourStream.GetDataHandle());
  302.             
  303.             ourFile.OpenDataFork(fsWrPerm);
  304.             ourFile.WriteDataFork(*ourStream.GetDataHandle(), ourStream.GetLength());
  305.             ourFile.CloseDataFork();
  306.         }
  307.     }
  308.     Catch_(inErr)
  309.     {
  310.         Str255 str;
  311.         
  312.         NumToString(inErr,str);
  313.         ParamText(inMacFSSpec->name, str, "\p", "\p");
  314.         CautionAlert(129, NULL);
  315.     } EndCatch_
  316. }
  317.  
  318. // * add a .dot extension to a Mac filename (yuk!)
  319. // * this would make a good alternate constructor argument for
  320. // * StPutFile.
  321. void AddDotExtension(Str255 ioString, const Str255 inDot)
  322. {
  323.     if(ioString[0] >= 32 - inDot[0]) //make space if necessary
  324.         ioString[0] -= inDot[0];
  325.     
  326.     BlockMoveData(&inDot[1], &ioString[ioString[0] + 1], inDot[0]);
  327.     ioString[0] +=inDot[0];
  328.     // * yeah, I know that can be optimized
  329. }
  330.  
  331. // * map a string to valid C chars only.
  332. // * --not very powerful or nice, but needs at
  333. // * least this level of translation to work properly
  334. void MapToValidC(Str255 ioString)
  335. {
  336.     long i;
  337.     
  338.     for(i = 1; i <= ioString[0]; i++)
  339.     {
  340.         if(ioString[i] == ' ' || ioString[i] == '\t')    //whitespace
  341.         {
  342.             ioString[i] = '_';
  343.         }
  344.         else if(ioString[i] > 128 || ioString[i] < 0x31)
  345.         {
  346.             ioString[i] = '_';
  347.         }
  348.     }
  349. }
  350.  
  351. void InsertTextIntoStream(Handle inOurResource, LStream &inStream)
  352. {
  353.     ThrowIfNULL_(inOurResource);
  354.     
  355.     HLockHi(inOurResource);
  356.     inStream.WriteData(*inOurResource, GetHandleSize(inOurResource));
  357.     HUnlock(inOurResource);
  358. }
  359.  
  360.  
  361. // * insert contents of a 'TEXT' resource into an LStream
  362. void InsertTextIntoStream(short inID, LStream &inStream)
  363. {
  364.     Handle ourResource = Get1Resource('TEXT', inID);
  365.     
  366.     InsertTextIntoStream(ourResource, inStream);
  367.     
  368. //    purposely don't dispose text - res manager serves as cache mechanism
  369. //    not an efficient one, to be sure, but it works.
  370. // * * * can't use this safely when other res forks are open unless
  371. // * * * guarantee our home currency
  372. }
  373.  
  374. void
  375. FrDropApp::DoQuit()
  376. {
  377.     mRunning = false;
  378. }